ez_DES

题目附件如下:

from Crypto.Cipher import DES  
import secrets  
import string  
  
flag = 'moectf{???}'  
characters = string.ascii_letters + string.digits + string.punctuation  
key = 'ezdes'+''.join(secrets.choice(characters) for _ in range(3))  
assert key[:5] == 'ezdes'  
key = key.encode('utf-8')  
l = 8  
  
def encrypt(text, key):  
    cipher = DES.new(key, DES.MODE_ECB)  
    padded_text = text + (l - len(text) % l) * chr(len(text))  
    data = cipher.encrypt(padded_text.encode('utf-8'))  
    return data  
  
c = encrypt(flag, key)  
print('c =', c)  
  
# c = b'\xe6\x8b0\xc8m\t?\x1d\xf6\x99sA>\xce \rN\x83z\xa0\xdc{\xbc\xb8X\xb2\xe2q\xa4"\xfc\x07'

作为密码赛道唯二50pts题目之一,此题用意在于让大家初步接触对称密码。
如果你已经了解过基础的DES等对称密码,可以直奔 part2 看解题代码。考虑到新生看的资料可能都是公钥密码范畴的,所以我在下面写几段介绍方便大家入门。

Part 1 对称密码基础

我们可以把密码算法分为两大类,一类是对称加密,另一类是非对称加密,它们的区别在于所使用的密钥是否是对称的。

假如 Alice 想要给 Bob 发消息,为了避免消息被窃取,他们有两种加密方案可以选择。

从中我们可以看出,对称加密和非对称加密各有所长,虽然当今时代非对称加密更主流一些(因为它相对来说更节约资源,且和互联网的传播更适配),但这也并不意味着对称加密就失去了价值。比如说,十几轮的置换和异或当然要比非对称加密里那些计算大整数的多少次方快很多。

对称加密里有两大门类:流密码分组密码。顾名思义,流密码(stream cipher)就像水流一样,从明文串开始横着往后流到密文串,分组密码(block cipher)就是对明文进行分块处理,再从前往后对每一块进行加密。这两者并不是互相冲突的概念,甚至可以相辅相成,例如祖冲之密码就是运用了分组密码思想的流密码。
本次赛题中,只有“杂交随机数”一题涉及到一点流密码,本题“ez_DES”以及“ez_AES”、“(半)^3部电台”这三题需要用到分组密码知识。

Part 2 题解

题目已经将密钥的前5位给出了,只需要遍历最后3位进行解密,而且解密也不需要自己另写函数

有同学可能要问了:直接暴力就完了?这么无脑?
对此我只能表示:毕竟暴力是密码学不可不品的一环
而且很多实际情况下确实只需要掌握调用函数的能力就足够了(

在进行分组加密前需要对明文进行填充,这里的填充方式是自定义的,不过对于解密来说无所谓,反正右大括号后面的对内容无影响

解题代码如下:

from Crypto.Cipher import DES  
import string  
import itertools  
  
characters = string.ascii_letters + string.digits + string.punctuation  
l = 8  
c = b'\xe6\x8b0\xc8m\t?\x1d\xf6\x99sA>\xce \rN\x83z\xa0\xdc{\xbc\xb8X\xb2\xe2q\xa4"\xfc\x07'  
  
def encrypt(text, key):  
    cipher = DES.new(key, DES.MODE_ECB)  
    padded_text = text+(l-len(text)%l)*chr(len(text))  
    data = cipher.encrypt(padded_text.encode('utf-8'))  
    return data  
  
def decrypt(data):  
    d = data[:8]  
    for keyy in itertools.product(characters, repeat=3):  
        print(keyy)  
        key2 = b'ezdes'+(''.join(keyy)).encode('utf-8')  
        for ch in characters:  
            r = encrypt('moectf{'+ch, key2)  
            if r[:8] == d:  
                print('key =',key2)  
                return key2  
    print('None!')  
  
  
key = decrypt(c)  
cipher = DES.new(key, DES.MODE_ECB)  
flag = cipher.decrypt(c)  
print(flag)  
  
# key = ezdes8br  
# flag = 'moectf{_Ju5t envmEra+e.!}'